#include "bsp.h"
#include "database_manager.h"
#include "spdlog/spdlog.h"
#include "qpcpp.hpp"
#include "auth_ao.h"
#include "db_ao.h"
#include "ui_ao.h"
#include "auth_events.h"
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <cstring>
#include <cstdio>
#include <sys/select.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>

// Local function declarations
static void consoleSetup();
static void consoleCleanup();
static int consoleGetKey();

namespace BSP
{

void init(int argc, char **argv)
{
    Q_UNUSED_PAR(argc);
    Q_UNUSED_PAR(argv);
    spdlog::info("BSP initialized");
    consoleSetup();
}

void start()
{
    spdlog::info("BSP: Initializing event pools");

    // Initialize event pools with minimal size for testing
    // Pool for small events (e.g., LogoutRequestEvt, DbSessionRemoveRequestEvt)
    static QF_MPOOL_EL(LogoutRequestEvt) smallPoolSto[10];
    QP::QF::poolInit(smallPoolSto, sizeof(smallPoolSto), sizeof(smallPoolSto[0]));
    spdlog::info("BSP: Small event pool initialized");

    // Pool for medium events (e.g., LoginRequestEvt, RegisterRequestEvt, SessionCheckRequestEvt, DbUserFindByUsernameRequestEvt, DbSessionFindByUserIdRequestEvt)
    static QF_MPOOL_EL(LoginRequestEvt) mediumPoolSto[10];
    QP::QF::poolInit(mediumPoolSto, sizeof(mediumPoolSto), sizeof(mediumPoolSto[0]));
    spdlog::info("BSP: Medium event pool initialized");

    // Pool for large events (e.g., DbUserCreateRequestEvt, DbSessionCreateRequestEvt, DbUserFindResponseSuccessEvt, DbUserCreateResponseSuccessEvt, DbSessionCreateResponseSuccessEvt, DbSessionFindResponseSuccessEvt)
    static QF_MPOOL_EL(DbUserCreateRequestEvt) largePoolSto[10];
    QP::QF::poolInit(largePoolSto, sizeof(largePoolSto), sizeof(largePoolSto[0]));
    spdlog::info("BSP: Large event pool initialized");

    // Initialize publish-subscribe
    static QP::QSubscrList subscrSto[50];
    QP::QActive::psInit(subscrSto, Q_DIM(subscrSto));
    spdlog::info("BSP: Publish-subscribe initialized");

    spdlog::info("BSP: All Active Objects started successfully");
}

void cleanup()
{
    // Cleanup resources if needed
}

// 在每个时钟滴答时检查终端输入
void onClockTick()
{
    // 处理 QP 时间事件
    QP::QTimeEvt::TICK_X(0U, nullptr);

    switch (consoleGetKey()) {
        case 'l': {
            spdlog::info("Login requested");
            // 发布登录事件
            LoginRequestEvt *loginEvt = Q_NEW(LoginRequestEvt, LOGIN_REQUEST_SIG);
            loginEvt->username = "testuser";
            loginEvt->password = "testpass";
            QP::QActive::PUBLISH(loginEvt, nullptr);
            break;
        }
        case 'r': {
            spdlog::info("Register requested");
            // 发布注册事件
            RegisterRequestEvt *registerEvt = Q_NEW(RegisterRequestEvt, REGISTER_REQUEST_SIG);
            registerEvt->username = "newuser";
            registerEvt->password = "newpass";
            QP::QActive::PUBLISH(registerEvt, nullptr);
            break;
        }
        case 'q': {
            spdlog::info("Quit requested");
            // 发布退出事件
            QP::QF::stop();
            break;
        }
        default: {
            break;
        }
    }
}

}  // namespace BSP

extern "C"
{

    Q_NORETURN Q_onError(char const *const module, int_t const id)
    {
        QS_ASSERTION(module, id, 10000U);  // report assertion to QS
        spdlog::error("Assertion failed in  {} :{}", module, id);
        QP::QF::onCleanup();
        QS_EXIT();
        exit(-1);
    }

    //............................................................................
    void assert_failed(char const *const module, int_t const id);  // prototype
    void assert_failed(char const *const module, int_t const id)
    {
        Q_onError(module, id);
    }

}  // extern "C"

// Console I/O implementation
namespace {
static struct termios l_old;
static struct termios l_new;
}

static void consoleSetup() {
    tcgetattr(0, &l_old);    // save the current terminal attributes
    l_new = l_old;           // copy the current attributes
    l_new.c_lflag &= ~(ICANON | ECHO); // disable canonical mode and echo
    l_new.c_cc[VMIN] = 0;    // minimum number of characters to read
    l_new.c_cc[VTIME] = 0;   // timeout in deciseconds
    tcsetattr(0, TCSANOW, &l_new); // set the new attributes
}

static void consoleCleanup() {
    tcsetattr(0, TCSANOW, &l_old); // restore the saved attributes
}

static int consoleGetKey() {
    int ch = 0;
    ssize_t n = read(0, &ch, 1);
    if (n <= 0) {
        ch = 0; // no key pressed
    }
    return ch;
}

// Implement QP::QF functions
namespace QP
{

void QF::onStartup(void)
{
}

void QF::onCleanup(void)
{
    BSP::cleanup();
}

void QF::onClockTick(void)
{
    BSP::onClockTick();  // 调用 BSP 的 onClockTick 函数
}

}  // namespace QP